{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Pandas 字符串切片和索引\n",
        "\n",
        "本教程系统讲解 Pandas 字符串切片（`str.slice`、`str.slice_replace`）与索引（`str.get`、`str[index]`）的用法，涵盖语法说明、边界情况和常见应用场景。\n",
        "\n",
        "## 学习目标\n",
        "\n",
        "- 理解 `str.slice()` 的参数含义与常见模式\n",
        "- 掌握 `str.slice_replace()` 进行局部替换的技巧\n",
        "- 使用 `str.get()`、`str[index]` 精确访问字符\n",
        "- 结合切片与索引解决数据清洗、字段拆分、脱敏等任务\n",
        "- 理解不同方法的优劣与性能特点\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 导入库\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [],
      "source": [
        "import pandas as pd\n",
        "import numpy as np\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 1. 创建示例数据\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>用户名</th>\n",
              "      <th>产品编号</th>\n",
              "      <th>手机号</th>\n",
              "      <th>描述</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>alice_001</td>\n",
              "      <td>PRD-2023-0001</td>\n",
              "      <td>138-1234-5678</td>\n",
              "      <td>订单#A100|状态:完成</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>bob_dev</td>\n",
              "      <td>PRD-2023-0002</td>\n",
              "      <td>139-9876-5432</td>\n",
              "      <td>订单#A101|状态:待付款</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>carol</td>\n",
              "      <td>PRD-2024-0001</td>\n",
              "      <td>137-0000-8888</td>\n",
              "      <td>订单#B200|状态:已发货</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>dave99</td>\n",
              "      <td>SRV-2023-0501</td>\n",
              "      <td>136-9999-2222</td>\n",
              "      <td>订单#C300|状态:已取消</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "         用户名           产品编号            手机号              描述\n",
              "0  alice_001  PRD-2023-0001  138-1234-5678   订单#A100|状态:完成\n",
              "1    bob_dev  PRD-2023-0002  139-9876-5432  订单#A101|状态:待付款\n",
              "2      carol  PRD-2024-0001  137-0000-8888  订单#B200|状态:已发货\n",
              "3     dave99  SRV-2023-0501  136-9999-2222  订单#C300|状态:已取消"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "data = pd.DataFrame({\n",
        "    '用户名': ['alice_001', 'bob_dev', 'carol', 'dave99'],\n",
        "    '产品编号': ['PRD-2023-0001', 'PRD-2023-0002', 'PRD-2024-0001', 'SRV-2023-0501'],\n",
        "    '手机号': ['138-1234-5678', '139-9876-5432', '137-0000-8888', '136-9999-2222'],\n",
        "    '描述': [\n",
        "        '订单#A100|状态:完成',\n",
        "        '订单#A101|状态:待付款',\n",
        "        '订单#B200|状态:已发货',\n",
        "        '订单#C300|状态:已取消'\n",
        "    ]\n",
        "})\n",
        "\n",
        "series_text = pd.Series([\n",
        "    'PYTHON',\n",
        "    'data-engineering',\n",
        "    '分析-2024-01',\n",
        "    'ID:998877'\n",
        "])\n",
        "\n",
        "data\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 2. `str.slice()` —— 定位+截取核心方法\n",
        "\n",
        "`Series.str.slice(start=None, stop=None, step=None)` 直接映射 Python 原生切片语义，但面向向量化字符串。\n",
        "\n",
        "- `start`: 起始位置（包含），默认从 0 开始\n",
        "- `stop`: 结束位置（不包含），默认直到字符串末尾\n",
        "- `step`: 步长，支持负数\n",
        "\n",
        "> 切片支持正向、反向、跨越多个字段的组合使用，适合从固定格式字段中取子串。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.1 固定位置截取（正向）\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>用户名</th>\n",
              "      <th>用户名前三位</th>\n",
              "      <th>产品编号</th>\n",
              "      <th>年份</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>alice_001</td>\n",
              "      <td>ali</td>\n",
              "      <td>PRD-2023-0001</td>\n",
              "      <td>2023</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>bob_dev</td>\n",
              "      <td>bob</td>\n",
              "      <td>PRD-2023-0002</td>\n",
              "      <td>2023</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>carol</td>\n",
              "      <td>car</td>\n",
              "      <td>PRD-2024-0001</td>\n",
              "      <td>2024</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>dave99</td>\n",
              "      <td>dav</td>\n",
              "      <td>SRV-2023-0501</td>\n",
              "      <td>2023</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "         用户名 用户名前三位           产品编号    年份\n",
              "0  alice_001    ali  PRD-2023-0001  2023\n",
              "1    bob_dev    bob  PRD-2023-0002  2023\n",
              "2      carol    car  PRD-2024-0001  2024\n",
              "3     dave99    dav  SRV-2023-0501  2023"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 截取用户名的前三个字符\n",
        "data['用户名前三位'] = data['用户名'].str.slice(stop=3)\n",
        "\n",
        "# 截取产品编号中的年份部分（索引 4~8）\n",
        "data['年份'] = data['产品编号'].str.slice(start=4, stop=8)\n",
        "\n",
        "data[['用户名', '用户名前三位', '产品编号', '年份']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.2 负索引与尾部截取\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>手机号</th>\n",
              "      <th>尾号</th>\n",
              "      <th>产品编号</th>\n",
              "      <th>流水号</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>138-1234-5678</td>\n",
              "      <td>5678</td>\n",
              "      <td>PRD-2023-0001</td>\n",
              "      <td>0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>139-9876-5432</td>\n",
              "      <td>5432</td>\n",
              "      <td>PRD-2023-0002</td>\n",
              "      <td>0002</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>137-0000-8888</td>\n",
              "      <td>8888</td>\n",
              "      <td>PRD-2024-0001</td>\n",
              "      <td>0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>136-9999-2222</td>\n",
              "      <td>2222</td>\n",
              "      <td>SRV-2023-0501</td>\n",
              "      <td>0501</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "             手机号    尾号           产品编号   流水号\n",
              "0  138-1234-5678  5678  PRD-2023-0001  0001\n",
              "1  139-9876-5432  5432  PRD-2023-0002  0002\n",
              "2  137-0000-8888  8888  PRD-2024-0001  0001\n",
              "3  136-9999-2222  2222  SRV-2023-0501  0501"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 截取手机号后四位\n",
        "\n",
        "data['尾号'] = data['手机号'].str.slice(start=-4)\n",
        "\n",
        "# 截取产品编号的后 4 个字符（流水号）\n",
        "data['流水号'] = data['产品编号'].str.slice(start=-4)\n",
        "\n",
        "data[['手机号', '尾号', '产品编号', '流水号']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.3 步长（step）与反向切片\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>用户名</th>\n",
              "      <th>步长2</th>\n",
              "      <th>手机号</th>\n",
              "      <th>手机号反转</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>alice_001</td>\n",
              "      <td>aie01</td>\n",
              "      <td>138-1234-5678</td>\n",
              "      <td>8765-4321-831</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>bob_dev</td>\n",
              "      <td>bbdv</td>\n",
              "      <td>139-9876-5432</td>\n",
              "      <td>2345-6789-931</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>carol</td>\n",
              "      <td>crl</td>\n",
              "      <td>137-0000-8888</td>\n",
              "      <td>8888-0000-731</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>dave99</td>\n",
              "      <td>dv9</td>\n",
              "      <td>136-9999-2222</td>\n",
              "      <td>2222-9999-631</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "         用户名    步长2            手机号          手机号反转\n",
              "0  alice_001  aie01  138-1234-5678  8765-4321-831\n",
              "1    bob_dev   bbdv  139-9876-5432  2345-6789-931\n",
              "2      carol    crl  137-0000-8888  8888-0000-731\n",
              "3     dave99    dv9  136-9999-2222  2222-9999-631"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 步长为 2 ，提取用户名偶数位字符\n",
        "data['步长2'] = data['用户名'].str.slice(step=2)\n",
        "\n",
        "# 反向切片，倒序手机号\n",
        "\n",
        "data['手机号反转'] = data['手机号'].str.slice(step=-1)\n",
        "\n",
        "data[['用户名', '步长2', '手机号', '手机号反转']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 2.4 同时对多个字段切片（DataFrame.apply）\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>用户名前4</th>\n",
              "      <th>产品编号前4</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>alic</td>\n",
              "      <td>PRD-</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>bob_</td>\n",
              "      <td>PRD-</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>caro</td>\n",
              "      <td>PRD-</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>dave</td>\n",
              "      <td>SRV-</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "  用户名前4 产品编号前4\n",
              "0  alic   PRD-\n",
              "1  bob_   PRD-\n",
              "2  caro   PRD-\n",
              "3  dave   SRV-"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 针对多列同时应用切片逻辑\n",
        "def extract_prefix(s):\n",
        "    return s.str.slice(stop=4)\n",
        "\n",
        "multi = data[['用户名', '产品编号']].apply(extract_prefix)\n",
        "multi.rename(columns={'用户名': '用户名前4', '产品编号': '产品编号前4'}, inplace=True)\n",
        "multi\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 3. `str.slice_replace()` —— 局部替换利器\n",
        "\n",
        "`Series.str.slice_replace(start=None, stop=None, repl=None)` 用切片定位要替换的部分，再填入 `repl`。\n",
        "\n",
        "- 默认 `start=0`，`stop=None`\n",
        "- 支持负索引与步长\n",
        "- 常见用法：脱敏、规范化格式、插入标记\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.1 脱敏：保留前后部分\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>手机号</th>\n",
              "      <th>手机号脱敏</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>138-1234-5678</td>\n",
              "      <td>138-****-5678</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>139-9876-5432</td>\n",
              "      <td>139-****-5432</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>137-0000-8888</td>\n",
              "      <td>137-****-8888</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>136-9999-2222</td>\n",
              "      <td>136-****-2222</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "             手机号          手机号脱敏\n",
              "0  138-1234-5678  138-****-5678\n",
              "1  139-9876-5432  139-****-5432\n",
              "2  137-0000-8888  137-****-8888\n",
              "3  136-9999-2222  136-****-2222"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 将手机号中间四位替换为 ****\n",
        "data['手机号脱敏'] = data['手机号'].str.slice_replace(start=4, stop=8, repl='****')\n",
        "\n",
        "data[['手机号', '手机号脱敏']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.2 插入标记或修复缺失片段\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>产品编号</th>\n",
              "      <th>标准编号</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>PRD-2023-0001</td>\n",
              "      <td>ITEM-2023-0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>PRD-2023-0002</td>\n",
              "      <td>ITEM-2023-0002</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>PRD-2024-0001</td>\n",
              "      <td>ITEM-2024-0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>SRV-2023-0501</td>\n",
              "      <td>ITEM-2023-0501</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "            产品编号            标准编号\n",
              "0  PRD-2023-0001  ITEM-2023-0001\n",
              "1  PRD-2023-0002  ITEM-2023-0002\n",
              "2  PRD-2024-0001  ITEM-2024-0001\n",
              "3  SRV-2023-0501  ITEM-2023-0501"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 将所有产品编号的前缀从 PRD/SRV 替换成统一的 ITEM-\n",
        "def normalize_prefix(value):\n",
        "    return value.str.slice_replace(stop=3, repl='ITEM')\n",
        "\n",
        "data['标准编号'] = normalize_prefix(data['产品编号'])\n",
        "\n",
        "data[['产品编号', '标准编号']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 3.3 负索引用于修改尾部\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>描述</th>\n",
              "      <th>描述_同步</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>订单#A100|状态:完成</td>\n",
              "      <td>订单#A100|状态已同步</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>订单#A101|状态:待付款</td>\n",
              "      <td>订单#A101|状态:已同步</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>订单#B200|状态:已发货</td>\n",
              "      <td>订单#B200|状态:已同步</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>订单#C300|状态:已取消</td>\n",
              "      <td>订单#C300|状态:已同步</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "               描述           描述_同步\n",
              "0   订单#A100|状态:完成   订单#A100|状态已同步\n",
              "1  订单#A101|状态:待付款  订单#A101|状态:已同步\n",
              "2  订单#B200|状态:已发货  订单#B200|状态:已同步\n",
              "3  订单#C300|状态:已取消  订单#C300|状态:已同步"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 将描述字段的状态修改为“已同步”，保留前半部分\n",
        "\n",
        "data['描述_同步'] = data['描述'].str.slice_replace(start=-3, repl='已同步')\n",
        "\n",
        "data[['描述', '描述_同步']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 4. `str.get()` 与 `str[index]` —— 精准定位单个字符\n",
        "\n",
        "- `Series.str.get(pos)`：返回指定位置的字符，支持负索引\n",
        "- `Series.str[indexer]`：语法糖，可直接写 `series.str[0]`\n",
        "- 取出的仍是 `Series`，可继续链式操作\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 4.1 获取单个字符并转换\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>产品编号</th>\n",
              "      <th>产品类型缩写</th>\n",
              "      <th>是否服务类</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>PRD-2023-0001</td>\n",
              "      <td>P</td>\n",
              "      <td>False</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>PRD-2023-0002</td>\n",
              "      <td>P</td>\n",
              "      <td>False</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>PRD-2024-0001</td>\n",
              "      <td>P</td>\n",
              "      <td>False</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>SRV-2023-0501</td>\n",
              "      <td>S</td>\n",
              "      <td>True</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "            产品编号 产品类型缩写  是否服务类\n",
              "0  PRD-2023-0001      P  False\n",
              "1  PRD-2023-0002      P  False\n",
              "2  PRD-2024-0001      P  False\n",
              "3  SRV-2023-0501      S   True"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 取产品编号首字符，判断类型\n",
        "data['产品类型缩写'] = data['产品编号'].str.get(0)\n",
        "data['是否服务类'] = data['产品类型缩写'].eq('S')\n",
        "\n",
        "data[['产品编号', '产品类型缩写', '是否服务类']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 4.2 负索引 & 链式判断\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>用户名</th>\n",
              "      <th>结尾字符</th>\n",
              "      <th>尾部为数字</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>alice_001</td>\n",
              "      <td>1</td>\n",
              "      <td>True</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>bob_dev</td>\n",
              "      <td>v</td>\n",
              "      <td>False</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>carol</td>\n",
              "      <td>l</td>\n",
              "      <td>False</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>dave99</td>\n",
              "      <td>9</td>\n",
              "      <td>True</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "         用户名 结尾字符  尾部为数字\n",
              "0  alice_001    1   True\n",
              "1    bob_dev    v  False\n",
              "2      carol    l  False\n",
              "3     dave99    9   True"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 判断用户名是否以数字结尾\n",
        "\n",
        "data['结尾字符'] = data['用户名'].str[-1]\n",
        "data['尾部为数字'] = data['结尾字符'].str.isnumeric()\n",
        "\n",
        "data[['用户名', '结尾字符', '尾部为数字']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 4.3 str.get + slice 组合\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>订单前缀</th>\n",
              "      <th>订单编号末位</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>订单#A100|状</td>\n",
              "      <td>状</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>订单#A101|状</td>\n",
              "      <td>状</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>订单#B200|状</td>\n",
              "      <td>状</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>订单#C300|状</td>\n",
              "      <td>状</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "        订单前缀 订单编号末位\n",
              "0  订单#A100|状      状\n",
              "1  订单#A101|状      状\n",
              "2  订单#B200|状      状\n",
              "3  订单#C300|状      状"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 先切片保留“订单#XXXX”，再取编号的最后一位\n",
        "orders = data['描述'].str.slice(stop=9)  # '订单#A100'\n",
        "data['订单编号末位'] = orders.str.get(-1)\n",
        "\n",
        "orders.to_frame(name='订单前缀').assign(订单编号末位=data['订单编号末位'])\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 5. 高阶场景：灵活切片策略\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 5.1 动态起止：配合 `str.find()`\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>描述</th>\n",
              "      <th>订单编号</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>订单#A100|状态:完成</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>订单#A101|状态:待付款</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>订单#B200|状态:已发货</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>订单#C300|状态:已取消</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "               描述  订单编号\n",
              "0   订单#A100|状态:完成   NaN\n",
              "1  订单#A101|状态:待付款   NaN\n",
              "2  订单#B200|状态:已发货   NaN\n",
              "3  订单#C300|状态:已取消   NaN"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 根据符号位置动态切片\n",
        "start_pos = data['描述'].str.find('#') + 1\n",
        "stop_pos = data['描述'].str.find('|')\n",
        "\n",
        "data['订单编号'] = data['描述'].str.slice(start=start_pos, stop=stop_pos)\n",
        "data[['描述', '订单编号']]\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 5.2 Series 与 DataFrame 互转\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>前缀</th>\n",
              "      <th>年份</th>\n",
              "      <th>序列</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>PRD</td>\n",
              "      <td>2023</td>\n",
              "      <td>0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>PRD</td>\n",
              "      <td>2023</td>\n",
              "      <td>0002</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>PRD</td>\n",
              "      <td>2024</td>\n",
              "      <td>0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>SRV</td>\n",
              "      <td>2023</td>\n",
              "      <td>0501</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "    前缀    年份    序列\n",
              "0  PRD  2023  0001\n",
              "1  PRD  2023  0002\n",
              "2  PRD  2024  0001\n",
              "3  SRV  2023  0501"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 将序列中的多个字段拆分成 DataFrame\n",
        "split_df = data['产品编号'].str.slice(stop=3).to_frame(name='前缀')\n",
        "split_df['年份'] = data['产品编号'].str.slice(4, 8)\n",
        "split_df['序列'] = data['产品编号'].str.slice(-4)\n",
        "\n",
        "split_df\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 5.3 处理缺失值与非字符串\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "0    123\n",
              "1       \n",
              "2       \n",
              "3    086\n",
              "dtype: object"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "mixed = pd.Series(['ABC123', None, np.nan, 10086])\n",
        "\n",
        "result = mixed.fillna('').astype(str).str.slice(-3)\n",
        "result\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 6. 实战案例\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 6.1 账号归一化：提取前缀+补零\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>原始</th>\n",
              "      <th>前缀</th>\n",
              "      <th>序号补齐</th>\n",
              "      <th>标准账号</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>CUS-1</td>\n",
              "      <td>CUS</td>\n",
              "      <td>0001</td>\n",
              "      <td>CUS0001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>CUS-23</td>\n",
              "      <td>CUS</td>\n",
              "      <td>0023</td>\n",
              "      <td>CUS0023</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>CUS-456</td>\n",
              "      <td>CUS</td>\n",
              "      <td>0456</td>\n",
              "      <td>CUS0456</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>VIP-9</td>\n",
              "      <td>VIP</td>\n",
              "      <td>0009</td>\n",
              "      <td>VIP0009</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "        原始   前缀  序号补齐     标准账号\n",
              "0    CUS-1  CUS  0001  CUS0001\n",
              "1   CUS-23  CUS  0023  CUS0023\n",
              "2  CUS-456  CUS  0456  CUS0456\n",
              "3    VIP-9  VIP  0009  VIP0009"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "accounts = pd.Series(['CUS-1', 'CUS-23', 'CUS-456', 'VIP-9'])\n",
        "\n",
        "prefix = accounts.str.slice(stop=3)\n",
        "serial = accounts.str.slice(start=4).str.zfill(4)\n",
        "normalized = prefix + serial\n",
        "\n",
        "pd.DataFrame({'原始': accounts, '前缀': prefix, '序号补齐': serial, '标准账号': normalized})\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 6.2 日志切片：定位级别与时间\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>日志</th>\n",
              "      <th>时间</th>\n",
              "      <th>级别</th>\n",
              "      <th>消息</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>2024-01-01 10:00:00 [INFO] Sync done</td>\n",
              "      <td>2024-01-01 10:00:00</td>\n",
              "      <td>INFO</td>\n",
              "      <td>Sync done</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2024-01-01 10:02:00 [ERROR] Timeout</td>\n",
              "      <td>2024-01-01 10:02:00</td>\n",
              "      <td>ERROR</td>\n",
              "      <td>Timeout</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>2024-01-01 10:03:00 [WARN] Slow query</td>\n",
              "      <td>2024-01-01 10:03:00</td>\n",
              "      <td>WARN</td>\n",
              "      <td>Slow query</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "                                      日志                   时间     级别  \\\n",
              "0   2024-01-01 10:00:00 [INFO] Sync done  2024-01-01 10:00:00   INFO   \n",
              "1    2024-01-01 10:02:00 [ERROR] Timeout  2024-01-01 10:02:00  ERROR   \n",
              "2  2024-01-01 10:03:00 [WARN] Slow query  2024-01-01 10:03:00   WARN   \n",
              "\n",
              "           消息  \n",
              "0   Sync done  \n",
              "1     Timeout  \n",
              "2  Slow query  "
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "logs = pd.Series([\n",
        "    '2024-01-01 10:00:00 [INFO] Sync done',\n",
        "    '2024-01-01 10:02:00 [ERROR] Timeout',\n",
        "    '2024-01-01 10:03:00 [WARN] Slow query'\n",
        "])\n",
        "\n",
        "time = logs.str.slice(stop=19)\n",
        "level = logs.str.slice(start=20, stop=26).str.strip('[]')\n",
        "message = logs.str.slice(start=27)\n",
        "\n",
        "pd.DataFrame({'日志': logs, '时间': time, '级别': level, '消息': message})\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### 6.3 票据号拆分：结合 `str.get` + `slice_replace`\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>原始票据</th>\n",
              "      <th>国家</th>\n",
              "      <th>序号</th>\n",
              "      <th>人类可读</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>INV2023CN001</td>\n",
              "      <td>CN</td>\n",
              "      <td>001</td>\n",
              "      <td>INV-20-CN-001</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>INV2023US002</td>\n",
              "      <td>US</td>\n",
              "      <td>002</td>\n",
              "      <td>INV-20-US-002</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>INV2024CN010</td>\n",
              "      <td>CN</td>\n",
              "      <td>010</td>\n",
              "      <td>INV-20-CN-010</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "           原始票据  国家   序号           人类可读\n",
              "0  INV2023CN001  CN  001  INV-20-CN-001\n",
              "1  INV2023US002  US  002  INV-20-US-002\n",
              "2  INV2024CN010  CN  010  INV-20-CN-010"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "tickets = pd.Series(['INV2023CN001', 'INV2023US002', 'INV2024CN010'])\n",
        "\n",
        "country = tickets.str.slice(7, 9)\n",
        "seq = tickets.str.slice(-3)\n",
        "# 构造新的可读票据\n",
        "readable = 'INV-' + tickets.str.get(3) + tickets.str.get(4) + '-' + country + '-' + seq\n",
        "\n",
        "pd.DataFrame({'原始票据': tickets, '国家': country, '序号': seq, '人类可读': readable})\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 7. 方法对比\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "| 方法 | 作用 | 典型参数 | 返回值 | 适用场景 |\n",
        "|------|------|----------|--------|----------|\n",
        "| `str.slice()` | 截取子串 | `start`, `stop`, `step` | Series | 固定结构字段拆分、反向切片 |\n",
        "| `str.slice_replace()` | 替换指定区间 | `start`, `stop`, `repl` | Series | 脱敏、插入标记、调整前缀 |\n",
        "| `str.get()` | 获取单个字符 | `pos` | Series | 分类、条件判断、链式操作 |\n",
        "| `str[index]` | 简写语法 | `series.str[0]` | Series | 简洁访问、配合布尔判断 |\n",
        "\n",
        "**选择建议**\n",
        "- 需要集合式截取 → `str.slice`\n",
        "- 需要保留原字符串大部分，仅改局部 → `str.slice_replace`\n",
        "- 只关心某一个字符 → `str.get` 或 `str[index]`\n",
        "- 动态范围 + 复杂逻辑 → 先计算位置索引，再传给 `str.slice`\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8. 总结\n",
        "\n",
        "1. `str.slice` 与 Python 切片保持一致，向量化后效率更高\n",
        "2. `str.slice_replace` 适合在不影响整体结构的情况下做局部替换\n",
        "3. `str.get`/`str[index]` 提供最细粒度的访问方式，可配合 `str.isnumeric()`、`str.upper()` 等\n",
        "4. 组合 `str.find`、`str.len` 可以实现动态切片\n",
        "5. 合理处理缺失值与数据类型（`fillna` + `astype(str)`）是批量处理的前提\n",
        "\n",
        "> 建议在调试时先对单个样本使用 Python 切片确认位置，再迁移到 `str.slice` 参数，能够大幅减少偏移错误。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "ml311",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
